package com.ansion.commonchat.startup.workmanager.bwork;

import androidx.annotation.NonNull;

import com.ansion.commonchat.startup.workmanager.bwork.impl.mode.BWorkSpec;
import com.ansion.commonchat.startup.workmanager.bwork.listener.BWorkListener;

import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.UUID;

/**
 * Created by wanghongjie on 2023/5/5
 * Describe : 定义后台任务的各种属性和配置，以满足具体的需求，并使用 WorkManager 进行任务的调度和管理。。
 */
public abstract class BWorkRequest {
    private @NonNull
    UUID mId;
    private @NonNull
    BWorkSpec mWorkSpec;
    private @NonNull
    Set<String> mTags;
    /**
     * 批量的workIds,用于批量监听Work。
     * 若 mBatchWorkIds 为null，但 mListener 不为null，则默认监听单个Work，即 getStringId 所指向的Work。
     */
    private final List<String> mBatchWorkIds;
    private final BWorkListener mListener;

    protected BWorkRequest(@NonNull UUID id, @NonNull BWorkSpec workSpec, @NonNull Set<String> tags, List<String> batchWorkIds, BWorkListener listener) {
        mId = id;
        mWorkSpec = workSpec;
        mTags = tags;
        mBatchWorkIds = batchWorkIds;
        mListener = listener;
    }

    public @NonNull
    UUID getId() {
        return mId;
    }

    public @NonNull
    String getStringId() {
        return mId.toString();
    }

    public @NonNull
    BWorkSpec getWorkSpec() {
        return mWorkSpec;
    }

    public @NonNull
    Set<String> getTags() {
        return mTags;
    }

    public List<String> getBatchWorkIds() {
        return mBatchWorkIds;
    }

    public BWorkListener getWorkListener() {
        return mListener;
    }

    public abstract static class Builder<B extends Builder<?, ?>, W extends BWorkRequest> {
        UUID mId;
        BWorkSpec mWorkSpec;
        Set<String> mTags = new HashSet<>();
        Class<? extends BListenableWorker> mWorkerClass;
        List<String> mBatchWorkIds;
        BWorkListener mListener;

        Builder(@NonNull Class<? extends BListenableWorker> workerClass) {
            mId = UUID.randomUUID();
            mWorkerClass = workerClass;
            mWorkSpec = new BWorkSpec(mId.toString(), workerClass.getName());
            addTag(workerClass.getName());
        }

        public final @NonNull
        B setInputData(@NonNull BData inputBData) {
            mWorkSpec.input = inputBData;
            return getThis();
        }

        public final @NonNull
        B addTag(@NonNull String tag) {
            mTags.add(tag);
            return getThis();
        }

        /**
         * 默认监听当前work，即 getStringId 所指向的Work。
         * <p>
         * 注意该方法与 @setBatchWorkListener 同时设置，则时序最后的生效。
         *
         * @param listener 监听者
         * @return
         */
        public final @NonNull
        B setWorkListener(BWorkListener listener) {
            mBatchWorkIds = null;
            mListener = listener;
            return getThis();
        }

        /**
         * 根据传入的批量的batchWorkIds，批量监听对应的work，其中任意一个Work变更，都会收到回调通知。
         * <p>
         * 注意该方法与 @setWorkListener 同时设置，则时序最后的生效。
         *
         * @param batchWorkIds 批量监听的Work的ids
         * @param listener     监听者
         * @return
         */
        public final @NonNull
        B setBatchWorkListener(List<String> batchWorkIds, BWorkListener listener) {
            mBatchWorkIds = batchWorkIds;
            mListener = listener;
            return getThis();
        }

        public final @NonNull
        W build() {
            W returnValue = buildInternal();
            mId = UUID.randomUUID();
            mWorkSpec = new BWorkSpec(mWorkSpec);
            mWorkSpec.id = mId.toString();
            return returnValue;
        }

        abstract @NonNull
        W buildInternal();

        abstract @NonNull
        B getThis();
    }
}